﻿using WinFormium.Forms;
using WinFormium;
using WinFormium.CefGlue;
using WinFormium.JavaScript;
using Teriri.File.Client.Function;
using Teriri.File.Client.Winform.Model;
using Teriri.File.UniversalLib.Helper;
using System.Reflection;

namespace Teriri.File.Client.Winform
{
    public class AppWindow : Formium
    {
        private string IpHost = "127.0.0.1:6000";
        private string VerifyToken = "Teriri";

        public AppWindow()
        {
            Url = "http://teriri.file.com/index.html";

            BeforeKeyEvent += AppWindow_BeforeKeyEvent;
        }

        private void AppWindow_BeforeKeyEvent(object sender, BeforeKeyEventEventArgs e)
        {
            if (e.KeyEvent.WindowsKeyCode == 123 && e.KeyEvent.EventType == CefKeyEventType.RawKeyDown)
            {
#if DEBUG
                if (HasDevTools)
                    CloseDevTools();
                else
                    ShowDevTools();
#endif
            }
        }

        protected override void OnLoaded(BrowserEventArgs args)
        {
            RegisterJavaScriptAsynchronousRequestDispatcher("GetFilesAndFolders", async (args, promise) =>
            {
                await this.GetFilesAndFolders(args, promise);
            });

            RegisterJavaScriptAsynchronousRequestDispatcher("DecompressingFile", async (args, promise) =>
            {
                await this.DecompressingFile(args, promise);
            });

            RegisterJavaScriptAsynchronousRequestDispatcher("DecompressingLog", async (args, promise) =>
            {
                await this.DecompressingLog(args, promise);
            });

            RegisterJavaScriptAsynchronousRequestDispatcher("DownloadFile", async (args, promise) =>
            {
                await this.DownloadFile(args, promise);
            });

            RegisterJavaScriptAsynchronousRequestDispatcher("SubmitServerConfig", async (args, promise) =>
            {
                await this.SubmitServerConfig(args, promise);
            });

            RegisterJavaScriptAsynchronousRequestDispatcher("GetServerConfig", async (args, promise) =>
            {
                await this.GetServerConfig(args, promise);
            });
        }

        protected override void PaintSplashScreen(PaintEventArgs e)
        {
            var assembly = Assembly.GetExecutingAssembly();
            using var stream = assembly.GetManifestResourceStream("Teriri.File.Client.Winform.wwwroot.startImage.png");
            e.Graphics.Clear(Color.White);
            e.Graphics.DrawImage(Image.FromStream(stream), -150, -150);
        }

        protected override FormStyle ConfigureWindowStyle(WindowStyleBuilder builder)
        {
            var style = builder.UseSystemForm();
            style.TitleBar = true;
            style.DefaultAppTitle = "文件管理";
            return style;
        }

        #region 自定义事件

        private async Task GetFilesAndFolders(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;

            try
            {
                var dir = args.GetString();
                var res = FileManageFunction.GetFilesAndFolders(IpHost, VerifyToken, dir);
                ReturnJsValue(promise, res);
            }
            catch (Exception ex)
            {
                LoggerHelper.Log<AppWindow>(ex);
                ReturnJsValue(promise, null, ex.Message);
            }
        }

        private async Task DecompressingFile(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;

            try
            {
                var path = args.GetString();
                FileManageFunction.DecompressingFile(IpHost, VerifyToken, path);
                ReturnJsValue(promise, null);
            }
            catch (Exception ex)
            {
                LoggerHelper.Log<AppWindow>(ex);
                ReturnJsValue(promise, null, ex.Message);
            }
        }

        private async Task DecompressingLog(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;

            try
            {
                var param = JsonHelper.Deserialize<dynamic>(args.GetString());
                int page = param.page;
                int limit = param.limit;
                var res = LogFunction.DecompressingLog(IpHost, VerifyToken, page, limit);
                ReturnJsValue(promise, res);
            }
            catch (Exception ex)
            {
                LoggerHelper.Log<AppWindow>(ex);
                ReturnJsValue(promise, null, ex.Message);
            }
        }

        private async Task DownloadFile(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;
            var path = args.GetString();

            try
            {
                var saveDirPath = Path.Combine(AppContext.BaseDirectory, "downloads");
                if(Directory.Exists(saveDirPath) == false)
                    Directory.CreateDirectory(saveDirPath);

                var savePath = Path.Combine(saveDirPath, Path.GetFileName(path));

                _ = FileManageFunction.DownloadFile(IpHost, VerifyToken, path, savePath, AppContext.BaseDirectory);

                ReturnJsValue(promise, null);
            }
            catch (Exception ex)
            {
                LoggerHelper.Log<AppWindow>(ex);
                ReturnJsValue(promise, null, ex.Message);
            }
        }

        private async Task SubmitServerConfig(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;

            try
            {
                var json = args.GetString();
                var param = JsonHelper.Deserialize<dynamic>(json);
                IpHost = param.iphost;
                VerifyToken = param.token;

                RpcClientHelper.Reconnect(IpHost, VerifyToken);

                var filePath = Path.Combine(AppContext.BaseDirectory, "serverInfo");
                if (System.IO.File.Exists(filePath) == false)
                    System.IO.File.Create(filePath).Dispose();

                using var writer = new StreamWriter(filePath);
                writer.Write(json);
            }
            catch (Exception ex)
            {
                ReturnJsValue(promise, null, ex.Message);
            }
        }

        private async Task GetServerConfig(JavaScriptValue args, JavaScriptPromise promise)
        {
            await Task.CompletedTask;

            var filePath = Path.Combine(AppContext.BaseDirectory, "serverInfo");
            if (System.IO.File.Exists(filePath) == false)
            {
                ReturnJsValue(promise, new { iphost = "", token = "" });
                return;
            }

            using var sr = new StreamReader(filePath);
            var json = sr.ReadToEnd();

            try
            {
                var data = JsonHelper.Deserialize<dynamic>(json);
                IpHost = data.iphost;
                VerifyToken = data.token;

                RpcClientHelper.Reconnect(IpHost, VerifyToken);
                ReturnJsValue(promise, new { iphost = IpHost, token = VerifyToken });
            }
            catch(Exception ex)
            {
                ReturnJsValue(promise, new { iphost = "", token = "" }, ex.Message);
            }
        }

        #endregion

        #region 工具方法

        private void ReturnJsValue(JavaScriptPromise promise, object data)
        {
            var model = new TeririRESTfulResult()
            {
                Code = 200,
                Data = data
            };

            promise.Resolve(JsonHelper.Serialize(model));
        }

        private void ReturnJsValue(JavaScriptPromise promise, object data, string errorMsg)
        {
            var model = new TeririRESTfulResult()
            {
                Code = 500,
                Data = data,
                Msg = errorMsg
            };

            promise.Resolve(JsonHelper.Serialize(model));
        }

        #endregion
    }
}
